#pragma once
#include <iostream>
#include <string>


#include "InetAddr.hxx"
#include "Log.hxx"
#include "nocopy.hpp"
#include "Common.hpp"
//LinuxC
#include <cerrno>
#include <unistd.h>
#include <cassert>
#include <cstring>
#include <functional>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/ftp.h>
#include <arpa/inet.h>
static int default_port = 43252;

const static int default_fd = -1;
const static int BufferSize = 4096;

using func_t = std::function<std::string(const std::string&)>;





class UdpServer: public nocopy
{
    std::string _ip;
    uint16_t _port;
    int _sockfd;
    Log lg;
    func_t _OnMessage;

    public:
    //只绑定一个Ip地址的版本
    UdpServer(const std::string &ip,uint16_t port  = default_port)
    :_ip(ip)
    ,_port(port)
    
    {
        
    }

    UdpServer(func_t OnMessage,uint16_t port  = default_port)
    :_port(port)
    ,_OnMessage(OnMessage)
    {
        
    }

    void Init()
    {
        _sockfd = socket(AF_INET,SOCK_DGRAM,0);
        if(_sockfd <0)
        {
            lg.Style(Log::PrintTo::LogFatal);
            lg(Log::MsgLevel::Fatal,"socket error ,%d,%s",errno,strerror(errno));
            exit(errno);
        }
        
        
        lg.Style(Log::PrintTo::Screen);
        lg(Log::MsgLevel::Info,"socket success, sockfd: %d ",_sockfd);
        
        struct sockaddr_in local;
        bzero(&local,sizeof(local));
        local.sin_family = AF_INET;//sin_family 实际就是一个短整型
        local.sin_port  = htons(_port);//host to net

        //一般来说，服务器不绑死一个固定的IP，因为那样就只能收到一个IP所接受的消息了
        //如下的绑定
        //local.sin_addr.s_addr = inet_addr(_ip.c_str());
        
        //我们一般采用另外的方式去绑定ip,就表示绑定任意地址，其宏值是0
        local.sin_addr.s_addr = INADDR_ANY;


        //用户空间的结构体到这里就填充完毕 


        
        //2.绑定网络消息
        int n =bind(_sockfd,(struct sockaddr*)&local,sizeof(local));

        if(n!=0)
        {
            lg.Style(Log::PrintTo::LogFatal);
            lg(Log::MsgLevel::Fatal,"bind error ,%d :%s\n",errno,strerror(errno));
            exit(Bind_error);
        }
    }

    void Start(){
        
        char buffer[BufferSize];
        for(;;)
        {
            struct  sockaddr_in peer;

            socklen_t len = sizeof(peer);
            ssize_t n = recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);

            if(n>0)
            {

                buffer[n] = 0;
                std::cout<< InetAddr_to_string(peer)\
                <<"Say#:"<<buffer<<"\n";
                std::string response = _OnMessage(buffer);
                //消息发回给client
                sendto(_sockfd,response.c_str(),response.size(),0,(struct sockaddr*)&peer,len);
            }

        }

    }
    ~UdpServer()
    {

    }
};


